package tw.fc.agui;

import java.lang.Thread;
import java.lang.Runnable;

import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.view.MotionEvent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Bitmap;
import android.graphics.Paint;

public abstract class GrSurfaceView extends SurfaceView 
                              implements GestureDetector.OnGestureListener,
                                         GestureDetector.OnDoubleTapListener,
                                         SurfaceHolder.Callback,
                                         Runnable{
    
   private final int DEFAULT_BG_COLOR= Color.argb(255, 153, 255, 153); //草綠色
   //[ 東西將繪製在此張 bitmap上
   private Bitmap NEW_BITMAP;
   //[ grCanvas模擬 java.awt.Graphics的方法, 供程式師繪圖
   private final GrCanvas GRCANVAS= new GrCanvas();
   
   
   
   private int bgColor= DEFAULT_BG_COLOR;
   //[ 負責發配各種觸碰事件
   private GestureDetector mDetector;    
   private SurfaceHolder   surfaceHolder;
   //[ 配合 lockCanvas()使用. 只是想避免重覆造指標
   private Canvas          tmpCanvas;     
   //[ 繪圖專用的執行緒
   private Thread          RENDER_ENGINE; 
   //[ 繪圖時經常會用到
   private  int             screenWidth, screenHeight;
   // ---------- construct ----------
   public GrSurfaceView(Context context) { 
      super(context);
      gestureDetector(context);
      surfaceDetector();
      //[ 取得設備的寬與高
      DisplayMetrics metrics = context.getResources().getDisplayMetrics();
      setBitmapIntoCanvas(metrics.widthPixels, metrics.heightPixels);
   }
   public GrSurfaceView(Context context, int w, int h) { 
      super(context);
      gestureDetector(context);
      surfaceDetector();
      setBitmapIntoCanvas(w,h);
   }
   public GrSurfaceView(Context context, AttributeSet attrs, int w, int h) { 
      super(context, attrs); 
      gestureDetector(context);
      surfaceDetector();
      setBitmapIntoCanvas(w,h);
   }
   public GrSurfaceView(Context context, AttributeSet attrs, int defStyle, int w, int h) { 
      super(context, attrs, defStyle); 
      gestureDetector(context);
      surfaceDetector();
      setBitmapIntoCanvas(w,h);
   }
   // ---------- construct ----------
   private final void gestureDetector(Context context) {
      mDetector = new GestureDetector(context, this);
      mDetector.setOnDoubleTapListener(this);
   }    
   private final void surfaceDetector() {
      surfaceHolder= getHolder();
      surfaceHolder.addCallback(this);
   }
   private final void setBitmapIntoCanvas(int width, int height) {         
      NEW_BITMAP=Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
      GRCANVAS.setBitmap(NEW_BITMAP);
      screenWidth= width; screenHeight= height;
   }
   
   
   public final void setBackground(int color) { bgColor= color; } 
   public final int getSW() { return screenWidth;  }
   public final int getSH() { return screenHeight; }
   
   //[ 本處設定 FPS的功能僅是簡單換算,
   //[ 實際的 FPS值會受繪製內容的複雜程度而變.
   //[ 另提供直接設定 sleep time的方法.
   private String  fpsTag      = "50 FPS";
   private long    lagTime     = 20;
   public final void setFPS(long f) { 
      if(f==0) {
         fpsTag= "maximum FPS"; lagTime= 0;
      } else {
         fpsTag= f+" FPS"; lagTime=1000/f; 
      }      
   }  
   public final void setSleepTime(long t) { lagTime= t; } 
   public final String queryFPSSetting() { return fpsTag; }
   //]
   
   //[ ---------- input event part ----------
   ////[ 供覆寫的反應函數, 若回傳 true表示觸碰行為往下繼續處理.   
   @Override 
   public boolean onFling(MotionEvent e1, MotionEvent e2, 
                          float velocityX, float velocityY){ 
      return true;
   }
   @Override 
   public boolean onScroll(MotionEvent e1, MotionEvent e2, 
                           float distanceX, float distanceY){ 
      return true;
   }
   @Override public boolean onDown(MotionEvent e)               { return true; }
   @Override public boolean onDoubleTap(MotionEvent e)          { return true; }
   @Override public boolean onDoubleTapEvent(MotionEvent e)     { return true; }
   @Override public boolean onSingleTapConfirmed(MotionEvent e) { return true; }
   @Override public boolean onSingleTapUp(MotionEvent e)        { return true; }
   @Override public void    onLongPress(MotionEvent e)          {}
   @Override public void    onShowPress(MotionEvent e)          {}
             public boolean    onMove(MotionEvent e)            { return true; }
             public boolean    onRelease(MotionEvent e)         { return true; }   
             public boolean onMultiTouchDown(MotionEvent e)     { return true; }
             public boolean onMultiTouchUp(MotionEvent e)       { return true; }
   ////]
   @Override
   public final boolean onTouchEvent(MotionEvent e) {
      boolean returnValue= true;   
      //[ ACTION_DOWN能被 onDown取代, 其他行為仍有存在的必要. 
      switch(MotionEventCompat.getActionMasked(e)) {
         case (MotionEvent.ACTION_MOVE) :
            returnValue= onMove(e);
            break;
         case (MotionEvent.ACTION_UP) :
            returnValue= onRelease(e);
            break;
         case (MotionEvent.ACTION_POINTER_DOWN) :
            returnValue= onMultiTouchDown(e);
            break;
         case (MotionEvent.ACTION_POINTER_UP) :
            returnValue= onMultiTouchUp(e);
            break;
      }
      if(returnValue) {
          returnValue= mDetector.onTouchEvent(e);
      }          
      return returnValue;  
   }
   //] ---------- input event part ----------
   
   //[ GrCanvas繼承 Canvas, 並擴充繪製點, 線, 面的方法,
   //[ 所擴充的方法使用方式與 java.awt.Graphics相同.
   //[
   //[ 因此, 當繼承 GrPanel時應覆寫 onDraw(GrCanvas grCanvas), 
   //[ 而非 onDraw(Canvas c).
   public void onDraw(GrCanvas grCanvas) {}
   boolean loopFlag=true;
   @Override
   public final void surfaceCreated(SurfaceHolder holder) { 
      RENDER_ENGINE= new Thread(this);
      RENDER_ENGINE.start();
      loopFlag=true;
   }
   @Override
   public final void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
   @Override
   public final void surfaceDestroyed(SurfaceHolder holder) { RENDER_ENGINE=null; loopFlag= false; }   
   @Override
   public void run() {
      while(loopFlag) {
         //[ ! 輸入事件更新速度比重繪速度快太多,
         //[   導致拖曳物件時, 還沒畫完就更新手指位置,
         //[   因此有殘像的狀況發生.
         //[   解決方式是: 存繪製頂點, 確保繪製完成後, 才在更新頂點位置.
         GRCANVAS.drawColor(bgColor);
         onDraw(GRCANVAS);
         ////[ 鎖定並取得畫面繪製權力, 避免主執行緒也同時使用
         tmpCanvas= surfaceHolder.lockCanvas();
         if(tmpCanvas!=null) {
         tmpCanvas.drawBitmap(NEW_BITMAP, 0, 0, new Paint());
         surfaceHolder.unlockCanvasAndPost(tmpCanvas);}
         ////] 解鎖, 繪製         
         try {
            RENDER_ENGINE.sleep(lagTime);
         } catch(Exception e) {
            Log.d("DebugMsg",e.getMessage());
         }
      }
   }
}
